package com.gezi.admin.security;

import cn.hutool.core.util.StrUtil;
import com.gezi.admin.config.redis.RedisUtil;
import com.gezi.admin.security.model.LoginClientEnum;
import com.gezi.admin.security.model.UserLoginAuthModel;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletRequest;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 认证相关配置项（注意这里的配置项一般都是加到配置文件上的）
 *
 * @Author 格子软件
 * @createDate 2024/2/10 09:00
 * @contact 公众号：格子软件 微信：13716343106 邮箱：1424529270@qq.com
 */
@Component
@Data
public class SecurityUtil {

    public static final String HEADER_TOKEN = "authorization";//token参数头
    public static final String HEADER_CLIENT = "client";//客户端
    public static final String BEARER = "Bearer_";//Token 的开头部分

    public static String springProfilesActive = "local";//激活配置
    public static Boolean weappTestEnable = false;//前端测试启动
    public static String weappTestUserId = "";//前端测试账号

    public static Boolean adminTestEnable = false;//后端测试启动
    public static String adminTestUserId = "";//后端测试账号
    public static String adminTestRole = "";//后端测试角色

    @Value("${spring.profiles.active}")
    public void springProfilesActive(String active) {
        SecurityUtil.springProfilesActive = active;
    }

    @Value("${gezi.test.enable}")
    public void securityIsTestUser(String isTestUser) {
        if (StrUtil.isNotBlank(isTestUser)) {
            if ("true".equals(isTestUser)) {
                SecurityUtil.weappTestEnable = true;
            }
        }
    }

    @Value("${gezi.test.userId}")
    public void securityTestUserId(String testUserId) {
        SecurityUtil.weappTestUserId = testUserId;
    }

    @Value("${gezi.testAdmin.enable}")
    public void securityIsTestAdminUser(String isTestUser) {
        if (StrUtil.isNotBlank(isTestUser)) {
            if ("true".equals(isTestUser)) {
                SecurityUtil.adminTestEnable = true;
            }
        }
    }

    @Value("${gezi.testAdmin.userId}")
    public void securityTestAdminUserId(String testUserId) {
        SecurityUtil.adminTestUserId = testUserId;
    }

    @Value("${gezi.testAdmin.role}")
    public void securityTestAdminRole(String role) {
        SecurityUtil.adminTestRole = role;
    }


    /**
     * 获取客户端
     *
     * @return
     */
    public static String getClient() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String client = request.getHeader(SecurityUtil.HEADER_CLIENT);
        if (StrUtil.isNotBlank(client)) {
            client = client.replace("-", "_");
        }
        return client;
    }

    /**
     * 获取用户id
     *
     * @return
     */
    public static String getUserId() {
        String client = getClient();
        if (LoginClientEnum.admin.isSame(client) && SecurityUtil.adminTestEnable.booleanValue()) {
            return SecurityUtil.adminTestUserId;
        } else if (!LoginClientEnum.admin.isSame(client) && SecurityUtil.weappTestEnable.booleanValue()) {
            return SecurityUtil.weappTestUserId;
        }
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication instanceof UsernamePasswordAuthenticationToken) {
            UsernamePasswordAuthenticationToken jwtAuthenticationToken = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
            if (jwtAuthenticationToken == null) {
                return "";
            }

            UserLoginAuthModel userLoginAuthModel = (UserLoginAuthModel) jwtAuthenticationToken.getPrincipal();
            return userLoginAuthModel.getUserId();
        } else {
            return "";
        }
    }

    public static List<String> getRoleList() {
        if (LoginClientEnum.admin.isSame(getClient()) && SecurityUtil.adminTestEnable.booleanValue()) {
            return Arrays.asList(SecurityUtil.adminTestRole);
        }
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication instanceof UsernamePasswordAuthenticationToken) {
            UsernamePasswordAuthenticationToken jwtAuthenticationToken = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
            if (jwtAuthenticationToken != null) {
                UserLoginAuthModel userLoginAuthModel = (UserLoginAuthModel) jwtAuthenticationToken.getPrincipal();
                return userLoginAuthModel.getRoleList();
            }
        }
        return Arrays.asList();
    }

    /**
     * token-redis 设置
     *
     * @param userId
     * @param value
     * @return
     */
    public static void setTokenToRedis(String client, String userId, Object value) {
        //设置普通存储
        RedisUtil.setNormalKey(getTokenRedisKey(client, userId), value);
        //设置过期时间
//        RedisUtil.setNormalKey(getTokenRedisKey(client,userId),value, 2L, TimeUnit.HOURS);
    }

    /**
     * 删除缓存
     *
     * @param client
     * @param userId
     */
    public static void delTokenToRedis(String client, String userId) {
        RedisUtil.deleteKey(getTokenRedisKey(client, userId));
    }

    /**
     * token-redis 是否存在或过期
     *
     * @param userId
     * @return
     */
    public static Boolean isTokenToRedis(String client, String userId) {
        String key = getTokenRedisKey(client, userId);
        if (RedisUtil.keyExist(key)) {
            return true;
        }
        return false;
    }

    /**
     * token-redis 设置续签
     *
     * @param userId
     * @return
     */
    public static void setXuqianToRedis(String client, String userId) {
        RedisUtil.setKeyExp(getTokenRedisKey(client, userId), 2L, TimeUnit.HOURS);
    }

    /**
     * token-redis 获取
     *
     * @param userId
     * @return
     */
    public static <T> T getTokenToRedis(String client, String userId) {
        return RedisUtil.<T>getNormalValue(getTokenRedisKey(client, userId));
    }

    /**
     * redis-token 获取key
     *
     * @param userId
     * @return
     */
    public static String getTokenRedisKey(String client, String userId) {
        String key = String.format("LOGIN:%s:%s", client, userId);
        return key;
    }
}